<template>
  <div class="hello">
    <div class="main">
      <div class="square">
        <spirit
          :value="item"
          :key="item.id"
          v-for="item in hallItems"
          :disable="!item.isTop"
          @click="hallClick(item)"
        />
      </div>
      <div class="assist">
        <div class="left">
          <spirit
            :value="item"
            :key="item.id"
            v-for="item in assistLeft"
            @click="assistClick(item)"
          />
        </div>
        <div class="right">
          <spirit
            :value="item"
            :key="item.id"
            v-for="item in assistRight"
            @click="assistClick(item)"
          />
        </div>
        <div class="toup">
          <spirit
            :value="item"
            :key="item.id"
            v-for="item in toupItems"
            @click="toupClick(item)"
          />
        </div>
      </div>
      <div class="box-slot">
        <spirit :value="item" :key="item.id" v-for="item in slotItems" />
      </div>
    </div>
    <div class="tools">
      <div class="btn renew" @click="renew">重来</div>
      <div class="btn toUp" @click="toUp3" :class="{ disable: toupNum == 0 }">
        上去
      </div>
      <div
        class="btn revoke"
        @click="revoke"
        :class="{ disable: revokeNum == 0 }"
      >
        撤销
      </div>
      <div
        class="btn disarrange"
        @click="disarrange"
        :class="{ disable: rangeNum == 0 }"
      >
        打乱
      </div>
    </div>
    <div v-if="isOver" class="over">GAME OVER!!!</div>
    <div v-if="isVictory" class="over">victory!!!</div>
  </div>
</template>

<script>
import spirit from "./spirit.vue";
const spirits = [
  {
    key: 1,
    icon: "ri-basketball-line",
  },
  {
    key: 2,
    icon: "ri-settings-4-line",
  },
  {
    key: 3,
    icon: "ri-notification-2-line",
  },
  {
    key: 4,
    icon: "ri-music-2-line",
  },
  {
    key: 5,
    icon: "ri-star-line",
  },
  {
    key: 6,
    icon: "ri-shield-star-line",
  },
  {
    key: 7,
    icon: "ri-aliens-line",
  },
  {
    key: 8,
    icon: "ri-sun-line",
  },
  {
    key: 9,
    icon: "ri-typhoon-line",
  },
  {
    key: 10,
    icon: "ri-fire-fill",
  },
  {
    key: 11,
    icon: "ri-key-2-line",
  },
  {
    key: 12,
    icon: "ri-knife-line",
  },
  {
    key: 13,
    icon: "ri-umbrella-line",
  },
  {
    key: 14,
    icon: "ri-plant-line",
  },
  {
    key: 15,
    icon: "ri-game-line",
  },
];
const assistNum = 10;
const layerNum = 10;
const ruleNum = 3;
export default {
  name: "hello-game",
  props: {
    count: {
      type: Number,
      default: 33,
    },
  },
  data() {
    return {
      allItems: [],
      isOver: false,
      isVictory: false,
      rangeNum: 0,
      toupNum: 0,
      revokeNum: 0,
      history: [],
    };
  },
  mounted() {
    this.renew();
  },
  components: { spirit },
  computed: {
    assistLeft() {
      let items = this.allItems
        .filter((x) => x.position == "assist-left" && !x.purge)
        .sort((a, b) => b.layer - a.layer);

      return items.map((item, idx) => {
        return {
          ...item,
          style: { left: idx * 4 + "px" },
        };
      });
    },
    assistRight() {
      let items = this.allItems
        .filter((x) => x.position == "assist-right" && !x.purge)
        .sort((a, b) => b.layer - a.layer);

      return items.map((item, idx) => {
        return {
          ...item,
          style: { right: idx * 4 + "px" },
        };
      });
    },
    slotItems() {
      let items = this.allItems
        .filter((x) => x.position == "slot")
        .sort((a, b) => a.order - b.order);
      return items.map((item, idx) => {
        return {
          ...item,
          style: { left: idx * 50 + "px" },
        };
      });
    },
    hallItems() {
      let items = this.allItems.filter((x) => x.position == "hall");
      items = items.map((item) => {
        let deviation = item.layer % 2 == 1 ? 0 : 25;
        let cols = item.layer % 2 == 1 ? 7 : 6;
        let sno = item.sno;
        let left = (sno % cols) * 50 + deviation;
        let top = Math.floor(sno / cols) * 50 + deviation;
        item.coordinate = {
          left,
          top,
        };

        return {
          ...item,
          style: {
            top: top + "px",
            left: left + "px",
            zIndex: item.layer,
          },
        };
      });
      items.forEach((item) => {
        if (!items.find((x) => x.layer > item.layer)) {
          item.isTop = true;
          return;
        }
        if (
          !items.find(
            (x) =>
              x.id != item.id &&
              x.layer > item.layer &&
              //左上
              ((x.coordinate.top == item.coordinate.top - 25 &&
                x.coordinate.left == item.coordinate.left - 25) ||
                //右下
                (x.coordinate.top == item.coordinate.top + 25 &&
                  x.coordinate.left == item.coordinate.left + 25) ||
                //右上
                (x.coordinate.top == item.coordinate.top - 25 &&
                  x.coordinate.left == item.coordinate.left + 25) ||
                //左下
                (x.coordinate.top == item.coordinate.top + 25 &&
                  x.coordinate.left == item.coordinate.left - 25) ||
                (x.coordinate.top == item.coordinate.top &&
                  x.coordinate.left == item.coordinate.left))
          )
        ) {
          item.isTop = true;
          return;
        }
        item.isTop = false;
      });
      return items;
    },
    toupItems() {
      let items = this.allItems
        .filter((x) => x.position == "to-up")
        .sort((a, b) => {
          a.order - b.order;
        });

      return items.map((item) => {
        return {
          ...item,
          style: {
            left: (item.order % 3) * 50 + "px",
            zIndex: item.order,
          },
        };
      });
    },
  },
  methods: {
    //新的开始
    renew() {
      let items = [];
      for (let i = 0; i < this.count; i++) {
        let spirit = Math.floor(Math.random() * spirits.length);
        for (let j = 0; j < ruleNum; j++) {
          items.push({
            id: i * ruleNum + j,
            spirit: spirits[spirit],
            order: Math.random(),
          });
        }
      }
      items = items.sort((a, b) => a.order - b.order);
      items = this.resetPosition(items, assistNum, assistNum, layerNum);

      this.allItems = items;
      this.isOver = false;
      this.isVictory = false;
      this.rangeNum = 1;
      this.toupNum = 2;
      this.revokeNum = 1;
      this.history = [];
    },
    //辅助点击
    assistClick(item) {
      if (this.isOver) {
        return;
      }
      let items =
        item.position == "assist-left" ? this.assistLeft : this.assistRight;
      if (items.find((x) => x.layer < item.layer)) {
        return;
      }
      this.slotAddItem(item);
    },
    //辅助点击
    hallClick(item) {
      if (this.isOver) {
        return;
      }
      if (!item.isTop) {
        return;
      }
      this.slotAddItem(item);
    },
    toupClick(item) {
      if (this.isOver) {
        return;
      }
      this.slotAddItem(item);
    },
    slotAddItem(item) {
      let items = this.allItems
        .filter((x) => x.position == "slot")
        .sort((a, b) => a.order - b.order);
      item.order = items.length;
      let idx = 0;
      items.forEach((s) => {
        let spirit = this.allItems.find((x) => x.id == s.id);
        spirit.order = idx++;
        if (item.spirit.key == spirit.spirit.key) {
          item.order = idx++;
        }
      });

      let his = [];
      his.push({
        id: item.id,
        position: item.position,
      });
      let spirit = this.allItems.find((x) => x.id == item.id);
      spirit.position = "slot";
      spirit.order = item.order;
      items = this.allItems.filter(
        (x) => x.position == "slot" && x.spirit.key == item.spirit.key
      );
      console.log(items);
      if (items.length == 3) {
        items.forEach((s) => {
          let spirit = this.allItems.find((x) => x.id == s.id);
          his.push({
            id: spirit.id,
            position: spirit.position,
          });
          spirit.position = "dispel";
        });
      }
      this.history.push(his);
      items = this.allItems.filter((x) => x.position == "slot");
      this.isOver = items.length > 6;
      items = this.allItems.filter((x) => x.position == "dispel");
      this.isVictory = items.length == this.allItems.length;
    },
    //打乱
    disarrange() {
      if (this.isOver) {
        return;
      }
      if (this.rangeNum == 0) {
        return;
      }
      let items = this.allItems.filter(
        (x) =>
          x.position == "assist-left" ||
          x.position == "assist-right" ||
          x.position == "hall"
      );
      this.history.push(
        items.map((x) => {
          return {
            id: x.id,
            // spirit: x.spirit,
            order: x.order,
            position: x.position,
            layer: x.layer,
            sno: x.sno,
          };
        })
      );
      items = items
        .map((x) => {
          return {
            id: x.id,
            spirit: x.spirit,
            order: Math.random(),
          };
        })
        .sort((a, b) => a.order - b.order);

      let left = this.assistLeft.length;
      let right = this.assistRight.length;
      let layer = Math.max(...this.hallItems.map((x) => x.layer)) || 0;
      items = this.resetPosition(items, left, right, layer + 1);
      let newItems = this.allItems.filter(
        (x) =>
          x.position != "assist-left" &&
          x.position != "assist-right" &&
          x.position != "hall"
      );
      // newItems = [];
      newItems.push(...items);
      this.allItems = newItems;
      this.rangeNum--;
    },
    //排序
    resetPosition(items, left, right, layer) {
      let index = 0;
      for (let i = 0; i < left; i++) {
        items[index].layer = i;
        items[index++].position = "assist-left";
      }
      for (let i = 0; i < right; i++) {
        items[index].layer = i;
        items[index++].position = "assist-right";
      }
      for (; index < items.length; index++) {
        items[index].layer = Math.floor(Math.random() * layer);
        items[index].position = "hall";
      }
      for (let i = 0; i < layer || 0; i++) {
        let cols = i % 2 == 1 ? 7 : 6;
        let total = cols * cols;
        // eslint-disable-next-line no-constant-condition
        while (true) {
          let item = items.find(
            (x) => x.position == "hall" && x.layer == i && x.sno === undefined
          );
          if (!item) {
            break;
          }
          let sno = Math.floor(Math.random() * total);
          while (
            items.find(
              (x) => x.position == "hall" && x.layer == i && x.sno == sno
            )
          ) {
            sno = Math.floor(Math.random() * total);
          }
          item.sno = sno;
        }
      }
      return items;
    },
    //上去三个
    toUp3() {
      if (this.isOver) {
        return;
      }
      if (this.toupNum == 0) {
        return;
      }
      if (this.slotItems.length < 3) {
        return;
      }
      let idx = this.toupItems.length == 0 ? 0 : 3;
      let his = [];
      for (let i = 0; i < 3; i++) {
        let s = this.slotItems[0];
        let item = this.allItems.find((x) => x.id == s.id);
        his.push({
          id: item.id,
          position: item.position,
          order: item.order,
        });
        item.position = "to-up";
        item.order = idx++;
      }
      this.history.push(his);
      this.toupNum--;
    },
    //撤销
    revoke() {
      if (this.isOver || this.isVictory) {
        return;
      }
      if (this.revokeNum == 0) {
        return;
      }
      if (this.history.length == 0) {
        return;
      }
      let his = this.history.pop();
      let len = his.length;
      for (let i = 0; i < len; i++) {
        let act = his.pop();
        let item = this.allItems.find((x) => x.id == act.id);
        item.position = act.position;
        if (act.order !== undefined) {
          item.order = act.order;
        }
        if (act.sno !== undefined) {
          item.sno = act.sno;
        }
        if (act.layer !== undefined) {
          item.layer = act.layer;
        }
      }
      this.revokeNum--;
    },
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello {
  position: relative;
  width: 400px;
  height: 625px;
  background-color: #000;
  margin: auto;
  padding: 25px;
}
.hello .over {
  background-color: #682;
  font-size: 2em;
  right: 20px;
  left: 20px;
  padding: 50px;
  text-align: center;
  top: 200px;
  color: #fff;
  position: absolute;
  z-index: 100;
}
.hello .main {
  position: relative;
  background: #333;
  width: 350px;
  height: 500px;
}
.hello .main .square {
  position: relative;
  background: #666;
  width: 350px;
  height: 350px;
}

.hello .main .assist {
  position: relative;
  background: #666;
  margin-top: 25px;
  width: 350px;
  height: 50px;
}
.hello .main .assist .toup {
  position: absolute;
  width: 150px;
  height: 50px;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
}
.hello .main .assist .left,
.hello .main .assist .right {
  position: relative;
  display: inline-block;
  background: #382;
  width: 175px;
  height: 50px;
}
.hello .main .box-slot {
  position: relative;
  background: #929;
  margin-top: 25px;
  width: 350px;
  height: 50px;
  overflow: hidden;
}
.hello .btn {
  display: inline-block;
  height: 50px;
  border: 1px solid yellow;
  text-align: center;
  color: #fff;
  background-color: green;
  width: 87.5px;
  font-size: 1em;
  padding-top: 12px;
  cursor: pointer;
}
.hello .tools {
  margin-top: 25px;
  position: relative;
  background: #333;
  width: 350px;
  height: 50px;
}

.hello .btn.disable {
  background-color: #aaa;
  cursor: no-drop;
}
</style>
